package service

import (
	sqlc "bgs/db/sqlc"
	"time"
	"bgs/util"
	"context"

	"encoding/json"
	"fmt"

)


type loggingAccountForOrderExt struct {
	OrderSerialNumber     string    `json:"order_serial_number"`
	Payed                 time.Time `json:"payed"`
	WxpayCommissionAmount int64     `json:"wxpay_fee"`
	BonusAmount           int64     `json:"order_bonus"`
}

// LoggingAccountForOrder 商家订单记账
func (s *BrandServiceImp) LoggingAccountForOrder(ctx context.Context, q *sqlc.Queries, orderPtr *sqlc.Order) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("==begin 商家订单记账")

	orderSerialNumber := orderPtr.SerialNumber

	// order, err := q.GetOrderBySerialNumber(ctx, orderSerialNumber)
	// if err != nil {
	// 	return err
	// }
	// slog.Infof("1、获取订单信息 ok")

	user, err := q.GetUser(ctx, orderPtr.UserID)
	if err != nil {
		return err
	}
	slog.Infof("1、获取下单用户信息 ok")

	payment, err := q.GetPaymentByOrderSerialNumber(ctx, orderSerialNumber)
	if err != nil {
		return err
	}
	slog.Infof("2、获取订单支付信息 ok")

	extInfoBytes, marshalErr := json.Marshal(&loggingAccountForOrderExt{
		OrderSerialNumber:     orderSerialNumber,
		Payed:                 payment.Payed.Time,
		WxpayCommissionAmount: orderPtr.WxpayCommissionAmount,
		BonusAmount:           orderPtr.BonusAmount,
	})
	if marshalErr != nil {
		err = marshalErr
		return
	}

	loggingParam := LoggingAccountParam{
		BrandID:  orderPtr.BrandID,
		IsIn:     true,
		Category: sqlc.EmBrandAccountLogCategoryOrder,
		Amount:   orderPtr.ActualAmount,
		Subject:  fmt.Sprintf("收款-%s", user.NickName.String),
		ExtInfo:  string(extInfoBytes),
	}

	err = s.loggingAccount(ctx, q, loggingParam)
	if err != nil {
		return
	}
	slog.Infof("3 商家账户变动日志(明细账)订单收款 ok")

	slog.Infof("==end 商家订单记账")
	return
}

// LoggingAccountForOrderRefundExt 商家订单退款记账结构
type LoggingAccountForOrderRefundExt struct {
	OrderSerialNumber     string    `json:"order_serial_number"`
	AfterSaleSerialNumber string    `json:"after_sale_serial_number"`
	Refunded              time.Time `json:"refunded"`
	WxpayFee              int64     `json:"wxpay_fee"`
	OrderBonus            int64     `json:"order_bonus"`
}

// LoggingAccountForOrderRefund 商家订单退款记账
func (s *BrandServiceImp) LoggingAccountForOrderRefund(ctx context.Context, q *sqlc.Queries, afterSalePtr *sqlc.AfterSale) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("==begin 商家订单退款记账")
	user, err := q.GetUser(ctx, afterSalePtr.UserID)
	if err != nil {
		return err
	}
	slog.Infof("1、获取售后单用户信息 ok")

	var orderBonusRefunded int64

	extInfoBytes, marshalErr := json.Marshal(&LoggingAccountForOrderRefundExt{
		OrderSerialNumber:     afterSalePtr.OrderSerialNumber,
		AfterSaleSerialNumber: afterSalePtr.SerialNumber,
		Refunded:              afterSalePtr.Refunded.Time,
		WxpayFee:              0,
		OrderBonus:            orderBonusRefunded,
	})
	if marshalErr != nil {
		err = marshalErr
		return
	}

	loggingParam := LoggingAccountParam{
		BrandID:  afterSalePtr.BrandID,
		IsIn:     false,
		Category: sqlc.EmBrandAccountLogCategoryRefund,
		Amount:   afterSalePtr.Amount,
		Subject:  fmt.Sprintf("退款-%s", user.NickName.String),
		ExtInfo:  string(extInfoBytes),
	}

	err = s.loggingAccount(ctx, q, loggingParam)
	if err != nil {
		return
	}
	slog.Infof("2 商家账户变动日志(明细账)订单售后退款 ok")

	_, err = q.MarkAfterSaleAccounted(ctx, afterSalePtr.ID)
	if err != nil {
		return
	}
	slog.Infof("3 标记售后单已记账 ok")

	slog.Infof("==end 商家订单退款记账 ok")
	return
}


// LoggingAccountForWithdrawExt 商家提现记账结构
type LoggingAccountForWithdrawExt struct {
	Applied      time.Time `json:"applied"`
	OutRequestNo string    `json:"out_request_no"`
	WxWithdrawID string    `json:"wx_withdraw_id"`
}

// LoggingAccountForOrderRefund 商家提现记账
func (s *BrandServiceImp) LoggingAccountForWithdraw(ctx context.Context, q *sqlc.Queries, brandAccountWithdrawApplymentPtr *sqlc.BrandAccountWithdrawApplyment) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	slog.Infof("==begin 商家提现记账记账")

	brandBankCard, err := q.GetBrandBankCard(ctx, brandAccountWithdrawApplymentPtr.BrandBankCardID)
	if err != nil {
		return
	}
	slog.Infof("1 获取商家提现银行卡信息 ok")

	extInfoBytes, marshalErr := json.Marshal(&LoggingAccountForWithdrawExt{
		Applied:      brandAccountWithdrawApplymentPtr.Applied,
		OutRequestNo: brandAccountWithdrawApplymentPtr.OutRequestNo.String,
		WxWithdrawID: brandAccountWithdrawApplymentPtr.WxWithdrawID.String,
	})
	if marshalErr != nil {
		err = marshalErr
		return
	}

	loggingParam := LoggingAccountParam{
		BrandID:  brandAccountWithdrawApplymentPtr.BrandID,
		IsIn:     false,
		Category: sqlc.EmBrandAccountLogCategoryWithdraw,
		Amount:   brandAccountWithdrawApplymentPtr.Amount,
		Subject:  fmt.Sprintf("提现-%s(%s)", brandBankCard.AccountBank, util.RightString(brandBankCard.AccountNumber, 4)),
		ExtInfo:  string(extInfoBytes),
	}

	err = s.loggingAccount(ctx, q, loggingParam)
	if err != nil {
		return
	}
	slog.Infof("2 商家账户变动日志(明细账)商家提现记账 ok")

	err = q.MarkBrandAccountWithdrawApplymentAccounted(ctx, brandAccountWithdrawApplymentPtr.ID)
	if err != nil {
		return
	}
	slog.Infof("3 标记商家提现申请已记账 ok")

	slog.Infof("==end 商家提现记账记账 ok")
	return
}

// LoggingAccountParam 记录品牌账户变动日志参数
type LoggingAccountParam struct {
	BrandID  int64
	IsIn     bool
	Category sqlc.EmBrandAccountLogCategory
	Amount   int64
	Subject  string
	ExtInfo  string
}

// LoggingAccount 记录品牌账户变动日志
func (s *BrandServiceImp) loggingAccount(ctx context.Context, q *sqlc.Queries, p LoggingAccountParam) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	_, err = q.CreateBrandAccountLog(ctx, sqlc.CreateBrandAccountLogParams{
		BrandID:  p.BrandID,
		IsIn:     p.IsIn,
		Category: string(p.Category),
		Amount:   util.Int64IfThenElse(p.IsIn, 1, -1) * p.Amount,
		Subject:  p.Subject,
		ExtInfo:  p.ExtInfo,
	})
	if err != nil {
		return
	}
	slog.Infof("创建品牌账户变动日志 ok")
	return
}